<template>
  <div class="hud-overlay-container" ref="overlayContainer">
    <div class="lock-box" ref="lockBox" v-show="showLockBox">
      <span class="hud-angle left top"></span>
      <span class="hud-angle right top"></span>
      <span class="hud-angle left bottom"></span>
      <span class="hud-angle right bottom"></span>
      <span class="hud-angle left top shadow"></span>
      <span class="hud-angle right top shadow"></span>
      <span class="hud-angle left bottom shadow"></span>
      <span class="hud-angle right bottom shadow"></span>
      <div class="edit-area" v-show="showEditArea">
        <div class="bg-frosted-class"></div>
        <div class="broadside-menu">
          <div
            class="broadside-menu-item-padding"
            @mouseenter="menuItemMouseEnterHandle('quit', '[退出]')"
            @mouseleave="menuItemMouseLeaveHandle('quit')"
            @click="clickQuitButton"
          >
            <div class="broadside-menu-item quit">
              <div class="icon quit"></div>
              <div class="icon quit shadow"></div>
              <div
                class="menu-item-description"
                v-show="showMenuItemDescription['quit']"
              >
                {{ menuItemDescription }}
              </div>
            </div>
          </div>
          <div
            class="broadside-menu-item-padding"
            @mouseenter="menuItemMouseEnterHandle('save', '[保存]')"
            @mouseleave="menuItemMouseLeaveHandle('save')"
            @click="clickSaveButton"
          >
            <div class="broadside-menu-item save">
              <div class="icon save"></div>
              <div class="icon save shadow"></div>
              <div
                class="menu-item-description"
                v-show="showMenuItemDescription['save']"
              >
                {{ menuItemDescription }}
              </div>
            </div>
          </div>
        </div>
        <span class="hud-angle left top"></span>
        <span class="hud-angle right top"></span>
        <span class="hud-angle left bottom"></span>
        <span class="hud-angle right bottom"></span>
        <span class="hud-angle left top shadow"></span>
        <span class="hud-angle right top shadow"></span>
        <span class="hud-angle left bottom shadow"></span>
        <span class="hud-angle right bottom shadow"></span>
        <div class="frosted-class-content">
          <component ref="component" :is="componentObj"></component>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import gsap from 'gsap'
import DynamicComponent from './DynamicComponent.vue'
export default {
  name: 'HudOverlay',
  components: { DynamicComponent },
  props: {
    anchorEl: Element,
    componentObj: Object
  },
  data () {
    return {
      showLockBox: false,
      showEditArea: false,
      menuItemDescription: {},
      showMenuItemDescription: {},
      animations: {}
    }
  },
  mounted () {
    this.$el.onselectstart = () => false
    this.lockAnchorEl()
    this.openingAnimation()
  },
  methods: {
    lockAnchorEl () {
      if (!this.anchorEl || !this.anchorEl.id) {
        return
      }
      let id = this.anchorEl.id
      let el = document.getElementById(id)
      let posInfo = el.getBoundingClientRect()
      gsap.set(this.$refs.lockBox, {
        top: posInfo.y + posInfo.height / 2 - 20,
        left: posInfo.x + posInfo.width / 2 - 20
      })
    },
    // 开场动画
    openingAnimation () {
      // TODO
      gsap
        .timeline()
        .set(this.$data, { showLockBox: true })
        .set(this.$data, { showEditArea: true })
    },
    clickQuitButton () {
      this.$emit('quit')
    },
    clickSaveButton () {
      this.$emit('save')
    },
    menuItemMouseEnterHandle (name, descriptionStr) {
      this.menuItemDescription = ''
      this.showMenuItemDescription[name] = true
      this.animations['itemDescription'] = this.strSpreadAnimation(
        descriptionStr,
        'menuItemDescription',
        false,
        null,
        0.05
      )
    },
    menuItemMouseLeaveHandle (name) {
      this.animations['itemDescription'].kill()
      this.showMenuItemDescription[name] = false
      this.menuItemDescription = ''
    },
    strSpreadAnimation (
      str,
      dataName,
      reverse,
      repeatLength,
      repeatDelay,
      onCompleteFunc
    ) {
      this[dataName] = ''
      if (str.length === 0) {
        return
      }
      let self = this
      let maskStr = reverse
        ? str.charAt(str.length - 1) + str
        : str.replace(/^./, '') + str.charAt(0)
      let repeatLen = repeatLength || str.length
      let i = reverse ? str.length - 1 : 0
      let step = true
      let strBackup
      return gsap.to(this.$data, {
        repeat: (repeatLen + 1) * 2,
        duration: repeatDelay || 0.04,
        onRepeat () {
          if (step) {
            strBackup = self[dataName]
            self[dataName] = reverse
              ? maskStr.charAt(i) + self[dataName]
              : self[dataName] + maskStr.charAt(i)
          } else {
            self[dataName] = reverse
              ? str.charAt(i--) + strBackup
              : strBackup + str.charAt(i++)
          }
          step = !step
        },
        onComplete: onCompleteFunc
      })
    },
    // TODO 不再使用,backdrop-filter:blur()可以替代这个功能
    // 将整个dom转为图片再使用高斯模糊
    toSvgImg () {
      // TODO 作为src参数,字符转义,需要进一步完善
      // TODO 或者转为base64?window.btoa()?需要单独处理中文字符, base64占用更多的内存和算力
      // TODO input缺少输入内容,使用HTMLDivElement对象作为传参??
      let svg =
        '<svg xmlns="http://www.w3.org/2000/svg" style="width:100%;height:100%;">' +
        this.styleTags.replace(/\/\*.+?\*\//g, '').replace(/#/g, '%23') +
        '<foreignObject width="100%" height="100%" requiredExtensions="http://www.w3.org/1999/xhtml">' +
        '<body xmlns="http://www.w3.org/1999/xhtml">' +
        this.html
          .replace(/<input(.+?)[/]?>/g, '<input$1 />')
          .replace(/<br(.*?)>/g, '<br />') +
        '</body>' +
        '</foreignObject>' +
        '</svg>'
      let data =
        'data:image/svg+xml;utf8,' + svg.replace(/"/g, "'").replace(/\n/g, '')
      // 在font-family设置某些字体后,如果存在多行文本的元素,不设置line-height,会导致生成的svg格式图片中的文本行高不同
      // 部分设置了百分比的元素可能出现错位问题
      // 布局样式参数还是元素中存在空格回车等字符引起???
      let overlayContainer = this.$el
      overlayContainer.style.backgroundImage = `url("${data}")`
    }
  }
}
</script>

<style scoped>
.hud-overlay-container {
  z-index: 100;
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  overflow: hidden;
  background-color: rgb(0, 0, 0, 0.45);
}
.lock-box {
  position: absolute;
  top: 100px;
  right: 400px;
  width: 40px;
  height: 40px;
}
.bg-frosted-class {
  position: absolute;
  overflow: hidden;
  width: 100%;
  height: 100%;
}
.bg-frosted-class::before {
  content: '';
  position: absolute;
  display: block;
  top: 0px;
  left: 0px;
  width: calc(100% + 10px);
  height: calc(100% + 10px);
  backdrop-filter: blur(1.8px);
  margin: -5px;
}
.frosted-class-content {
  z-index: 101;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 430px;
  max-height: 100%;
  text-align: center;
  overflow-x: hidden;
  word-wrap: break-word;
  color: rgba(255, 255, 255, 0.5);
  text-shadow: 0px 0px 3px rgba(255, 255, 255, 0.5);
}
.frosted-class-content::-webkit-scrollbar {
  width: 0;
}
.edit-area {
  position: absolute;
  top: 0;
  right: calc(100% + 8px);
  margin: auto;
  width: 500px;
  height: 250px;
  background: inherit;
}
.hud-angle {
  z-index: 101;
  position: absolute;
  display: inline-block;
  border: 2px solid rgba(255, 255, 255, 1);
  width: 12px;
  height: 12px;
}
.hud-angle.left.top {
  top: 0;
  left: 0;
  border-right-width: 0px;
  border-bottom-width: 0px;
}
.hud-angle.right.top {
  top: 0;
  right: 0;
  border-left-width: 0px;
  border-bottom-width: 0px;
}
.hud-angle.left.bottom {
  bottom: 0;
  left: 0;
  border-right-width: 0px;
  border-top-width: 0px;
}
.hud-angle.right.bottom {
  right: 0;
  bottom: 0;
  border-left-width: 0px;
  border-top-width: 0px;
}
.broadside-menu {
  position: absolute;
  top: 100%;
  right: 0;
  padding-top: 5px;
}
.broadside-menu-item-padding {
  z-index: 101;
  position: relative;
  display: inline-block;
  cursor: pointer;
  padding: 10px;
  margin-right: 10px;
}
.broadside-menu-item {
  position: relative;
  width: 20px;
  height: 20px;
}
.shadow {
  filter: blur(2px);
}
.icon {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  margin: auto;
}
/* .icon.save {
  width: 43%;
  height: 83%;
  border-color: white;
  border-style: solid;
  border-width: 0 3px 3px 0;
  transform: rotate(45deg);
} */
.icon.save {
  width: 60%;
  height: 60%;
  border-color: white;
  border-style: solid;
  border-width: 3px;
  border-radius: 100%;
  transform: rotate(45deg);
}
.icon.quit {
  width: 100%;
  height: 3px;
  background-color: white;
  transform: rotate(45deg);
}
.icon.quit::before {
  content: '';
  display: block;
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  margin: auto;
  width: 100%;
  height: 3px;
  background-color: white;
  transform: rotate(90deg);
}
.menu-item-description {
  position: absolute;
  top: calc(100% + 7px);
  left: -50%;
  white-space: nowrap;
  color: white;
  text-shadow: 0px 0px 3px white;
}
</style>
